﻿using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;

namespace QuDao
{
    public static class Extensions
    {
        /// <summary>
        /// 从阿里云OSS地址中解析出对应的OssKey
        /// </summary>
        /// <param name="ossUrl">阿里云OSS地址</param>
        /// <param name="prifix">OssKey前缀</param>
        /// <returns></returns>
        public static string GetOssKey(this string ossUrl, string prefix = "qudao")
        {
            return Utils.GetOssKey(ossUrl, prefix);
        }

        /// <summary>
        /// 获取指定日期的星期名称（例如：周日或者星期天）
        /// </summary>
        /// <param name="date">日期</param>
        /// <param name="prefix">仅支持“周”和“星期”为前缀</param>
        /// <returns></returns>
        public static string GetWeekName(this DateTime date, string prefix = "周")
        {
            switch (date.DayOfWeek)
            {
                case DayOfWeek.Friday:
                    return prefix == "周" ? "周五" : "星期五";
                case DayOfWeek.Monday:
                    return prefix == "周" ? "周一" : "星期一";
                case DayOfWeek.Saturday:
                    return prefix == "周" ? "周六" : "星期六";
                case DayOfWeek.Sunday:
                    return prefix == "周" ? "周日" : "星期天";
                case DayOfWeek.Thursday:
                    return prefix == "周" ? "周四" : "星期四";
                case DayOfWeek.Tuesday:
                    return prefix == "周" ? "周二" : "星期二";
                case DayOfWeek.Wednesday:
                    return prefix == "周" ? "周三" : "星期三";
                default:
                    return string.Empty;
            }
        }
    }

    public static class ObjectgExtensions
    {

        #region Object Extensions
        /// <summary>
        /// 通过反射的方式来简单的复制对象（复杂对象映射请使用AutoMapper）
        /// </summary>
        /// <typeparam name="T">拷贝数据目标对象类型</typeparam>
        /// <param name="source">拷贝数据来源对象</param>
        /// <param name="target">目标对象</param>
        /// <returns></returns>
        public static T CopyTo<T>(this object source, T target)
        {
            if (target == null) target = Activator.CreateInstance<T>();

            var sourceType = source.GetType();
            foreach (var targetItem in target.GetType().GetProperties())
            {
                var sourceItem = sourceType.GetProperty(targetItem.Name); ;
                if (sourceItem != null)
                {
                    targetItem.SetValue(target, sourceItem.GetValue(source));
                }
            }
            return target;
        }

        /// <summary>
        /// 通过反射的方式来简单的复制对象（复杂对象映射请使用AutoMapper）
        /// </summary>
        /// <typeparam name="T">拷贝数据目标对象类型</typeparam>
        /// <param name="source">拷贝数据来源对象</param>
        /// <returns></returns>
        public static T CopyTo<T>(this object source)
        {
            return source.CopyTo<T>(default);
        }
        #endregion

    }

    public static class ArrayExtensions
    {
        public static int[] ToIntArray(this string[] arr)
        {
            var result = Utils.ConvertStringArrayToIntArray(arr);
            return result;
        }
    }

    public static class ImageSharpExtention
    {
        /// <summary>
        /// 给当前处理的图片加水印
        /// </summary>
        /// <param name="processingContext">当前图片处理上下文对象</param>
        /// <param name="waterStream">水印图片文件流</param>
        /// <param name="waterPosition">水印位置：lefttop，topcenter，righttop，rightcenter，rightbottom，bottomcenter，leftbottom，leftcenter，center-中间</param>
        /// <param name="opacity">透明度，默认1，不透明</param>
        /// <returns></returns>
        public static IImageProcessingContext ApplyScalingImageWaterMark(this IImageProcessingContext processingContext, Stream waterStream, string waterPosition = "center", float opacity = 1)
        {
            using var mark_image = Image.Load(waterStream);
            int markWidth = mark_image.Width;
            int markHeight = mark_image.Height;

            var imgSize = processingContext.GetCurrentSize();

            if (markWidth >= imgSize.Width || markHeight >= imgSize.Height) //对水印图片进行缩放
            {
                if (imgSize.Width > imgSize.Height)//横的长方形
                {
                    markWidth = imgSize.Width / 2; //宽缩放一半
                    markHeight = (markWidth * imgSize.Height) / imgSize.Width;
                }
                else
                {
                    markHeight = imgSize.Height / 2;
                    markWidth = (markHeight * imgSize.Width) / imgSize.Height;
                }
                mark_image.Mutate(mk => mk.Resize(markWidth, markHeight));
            }
            //水印图片完成成立，开始根据位置添加水印
            var position = waterPosition;
            if (string.IsNullOrEmpty(position))
            {
                position = "center";
            }
            position = position.ToLower();
            if (string.IsNullOrEmpty(position))
            {
                position = "center";
            }

            var point = new Point();
            //左上
            if (position.Contains("lefttop"))
            {
                point.X = 10;
                point.Y = 10;
            }
            //上中
            if (position.Contains("topcenter"))
            {
                point.X = (imgSize.Width - mark_image.Width) / 2;
                point.Y = 10;
            }
            //右上
            if (position.Contains("righttop"))
            {
                point.X = (imgSize.Width - mark_image.Width) - 10;
                point.Y = 10;
            }
            //右中
            if (position.Contains("rightcenter"))
            {
                point.X = (imgSize.Width - mark_image.Width) - 10;
                point.Y = (imgSize.Height - mark_image.Height) / 2;
            }
            //右下
            if (position.Contains("rightbottom"))
            {
                point.X = (imgSize.Width - mark_image.Width) - 10;
                point.Y = (imgSize.Height - mark_image.Height) - 10;
            }
            //下中
            if (position.Contains("bottomcenter"))
            {
                point.X = (imgSize.Width - mark_image.Width) / 2;
                point.Y = (imgSize.Height - mark_image.Height) - 10;
            }
            //左下
            if (position.Contains("leftbottom"))
            {
                point.X = 10;
                point.Y = (imgSize.Height - mark_image.Height) - 10;
            }
            //左中
            if (position.Contains("leftcenter"))
            {
                point.X = 10;
                point.Y = (imgSize.Height - mark_image.Height) / 2;
            }
            if (position.Contains("center"))
            {
                point.X = (imgSize.Width - mark_image.Width) / 2;
                point.Y = (imgSize.Height - mark_image.Height) / 2;
            }

            //添加水印
            return processingContext.DrawImage(mark_image, point, opacity);


        }

        // Implements a full image mutating pipeline operating on IImageProcessingContext
        public static IImageProcessingContext ConvertToAvatar(this IImageProcessingContext context, Size size, float cornerRadius)
        {
            return context.Resize(new ResizeOptions
            {
                Size = size,
                Mode = ResizeMode.Crop
            }).ApplyRoundedCorners(cornerRadius);
        }


        // This method can be seen as an inline implementation of an `IImageProcessor`:
        // (The combination of `IImageOperations.Apply()` + this could be replaced with an `IImageProcessor`)
        private static IImageProcessingContext ApplyRoundedCorners(this IImageProcessingContext context, float cornerRadius)
        {
            Size size = context.GetCurrentSize();
            IPathCollection corners = BuildCorners(size.Width, size.Height, cornerRadius);

            context.SetGraphicsOptions(new GraphicsOptions()
            {
                Antialias = true,

                // Enforces that any part of this shape that has color is punched out of the background
                AlphaCompositionMode = PixelAlphaCompositionMode.SrcAtop
            });

            // Mutating in here as we already have a cloned original
            // use any color (not Transparent), so the corners will be clipped
            foreach (IPath path in corners)
            {
                context = context.Fill(Color.White, path);
            }

            return context;
        }

        private static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
        {
            // First create a square
            var rect = new RectangularPolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);

            // Then cut out of the square a circle so we are left with a corner
            IPath cornerTopLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));

            // Corner is now a corner shape positions top left
            // let's make 3 more positioned correctly, we can do that by translating the original around the center of the image.

            float rightPos = imageWidth - cornerTopLeft.Bounds.Width + 1;
            float bottomPos = imageHeight - cornerTopLeft.Bounds.Height + 1;

            // Move it across the width of the image - the width of the shape
            IPath cornerTopRight = cornerTopLeft.RotateDegree(90).Translate(rightPos, 0);
            IPath cornerBottomLeft = cornerTopLeft.RotateDegree(-90).Translate(0, bottomPos);
            IPath cornerBottomRight = cornerTopLeft.RotateDegree(180).Translate(rightPos, bottomPos);

            return new PathCollection(cornerTopLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
        }
    }
}
